AI 讓產生測試的成本趨近於零,瓶頸整個移動了:現在稀缺的不是測試,是「確認測試真的在把關」的能力。綠燈很便宜,可信的綠燈很貴。這篇教你怎麼讓綠燈變貴。
先講清楚:這篇用到的方法,業界早就有,不是新發明。靜態檢查規則、故意讓測試紅一次確認它會叫、抽樣審查,每一項都是既有做法。差別在於以前這些是「有空再做」,在 AI 一天產出過去一個月測試量的情況下,它們變成日常。
這篇你會帶走三件可以馬上做的事
一、假綠燈:報告很漂亮,警報器是壞的
圖 1:三種假綠燈,共同點是報告上看不出來
三種假綠燈,由淺到深:
三者的共同點:報告上一片綠,平時完全無症狀。這正是麻煩所在——假綠燈沒辦法用「看報告」發現,因為它的症狀就是報告很正常。
要驗警報器,只有一個辦法:製造火災。
二、第一層防線:讓機器自動抓(設定一次,長期受用)
三種假綠燈裡,第一種跟第三種不需要人看,工具就抓得到。這是業界標準配備,測試人員可以直接向工程師提出要求,不需要自己寫程式。
2.1 開啟 lint 規則
Playwright 專案用 eslint-plugin-playwright,Jest 或 Vitest 專案用對應的 eslint-plugin-jest / eslint-plugin-vitest。要開的規則就這幾條:
2.2 在 CI 上加一道保險
• 執行指令加上 --forbid-only:只要有人留了 test.only,CI 直接失敗。
• 每次看報告,不要只看「通過幾支」,也看「跳過幾支」。skipped 的數字悄悄變多,是最容易被忽略的警訊。
• 把測試報告設成保留歷史。後面第五節會用到「這支測試多久沒紅過」這個資訊。
2.3 這一層抓不到什麼
抓不到「斷言錯位」。它有 expect、格式也對,只是驗錯地方。這種只能靠人,也就是下一節的主角。
💬 提示詞 1:請 AI 幫你把這層設定起來
我們是 Playwright + TypeScript 的專案。請幫我安裝並設定 eslint-plugin-playwright,開啟這幾條規則:expect-expect、no-skipped-test、no-focused-test、no-conditional-expect、valid-expect。
設定完之後,對現有的測試檔跑一次 lint,把違規清單列給我,包含檔名跟行數。先不要自動修,我要先看有多少。
這段提示詞為什麼這樣寫:
三、第二層防線:弄壞它,看警報器叫不叫(這節是核心)

圖 2:驗證一個測試的循環
方法你在第 3 篇就做過,現在升格為紀律。挑一個測試宣稱守護的行為,刻意弄壞它,跑測試。
該紅而紅:警報器可信,改回來,收工。
該紅卻綠:恭喜,你在使用者之前發現了一個假警報器。補強斷言,再弄壞一次,直到它會叫。
整個流程五分鐘就跑得完,不需要會寫程式,也不需要另外裝任何工具。你要的只是一個念頭:綠燈不是結論,是待證明的假設。
3.1 兩種弄壞法,強度不一樣
A 只能證明斷言活著,B 才能證明它守對地方。麻煩的是你多半沒有、也不該有直接改產品程式的權限。實務上兩條路:請工程師在他本機臨時改一行,你跑一次;或者請 AI 在一個臨時分支上改,跑完立刻還原。
⚠️ 做法 B 的三條安全線
只在本機或臨時分支做,絕對不推上去。
開始前確認工作區是乾淨的(git status),結束後還原(git restore),確認真的還原了。
一次只弄壞一個地方。同時弄壞兩處,測試紅了你分不清是誰造成的。
3.2 核心提示詞
💬 提示詞 2:完整的一輪弄壞驗證
我想驗證「年齡檢核」的測試有沒有真的在把關。請照下面的順序做,每一步都告訴我結果:
1. 先只跑這一支測試,確認現在是通過的。
2. 把測試的預期改成錯的(把「應該擋下 17 歲」改成「應該接受 17 歲」),重跑,確認它會失敗,並把失敗訊息貼給我。
3. 把測試改回原狀,重跑,確認恢復通過。
過程中不要為了讓測試通過而修改任何斷言或等待條件。如果結果跟預期不同,直接告訴我,不要自己調整。
最後回答我兩個問題:如果產品端的年齡檢核邏輯整個被移除,現在這些測試抓得到嗎?這個功能還有哪些行為,目前沒有任何測試在守?
這段提示詞為什麼這樣寫:
把 AI 用在質疑 AI 的產出上,是這個時代最划算的槓桿之一。但有一句要記牢:AI 說「這樣會失敗」不算數,你親眼看到紅色才算數。
3.3 「驗到哪一層」是斷言錯位的解藥
斷言錯位之所以難抓,是因為它長得很正常。有一個很實用的判斷方式:問這個斷言驗到哪一層。
實務上的原則:畫面訊息可以驗,但核心流程不要只驗它。付款、權限、金額計算這幾類,至少要有一層驗到 API 或資料。
好消息是這件事你自己就能做。Playwright 內建的 request 功能可以在同一支測試裡直接呼叫 API 做確認,不必等工程師另外幫你寫東西。
💬 提示詞 3:把斷言往下推一層
這支測試現在只驗畫面上出現「訂單成立」。請幫我加一層更硬的驗證:在同一支測試裡用 Playwright 的 request 呼叫訂單查詢 API,確認這筆訂單真的存在,而且金額跟狀態都正確。
原本畫面的驗證保留,不要刪掉。加上去之後跑一次,把結果給我。
另外告訴我:如果後端根本沒有寫入這筆訂單,新加的這段驗證抓不抓得到?
四、抽查的紀律:不必全驗,但必須有驗
每一支測試都這樣驗一次,成本吃不消,也不必要。合理的抽查策略:
原則跟你做抽樣檢驗一樣:抽查的目的不是覆蓋,是嚇阻,加上估計整體品質。連抽的都有問題,整批退回重審——這比一支一支修有效率得多。
4.1 一個不用花力氣就有的訊號
一支測試如果從建立到現在從來沒有紅過,只有兩種可能:功能真的很穩,或者它根本不會叫。你分不出是哪一種,所以它就該被抽查。
多數 CI 平台都留得住歷史結果,GitHub Actions、GitLab CI、Jenkins 的測試報告外掛都可以。請工程師撈一份「近半年從未失敗的測試清單」給你,那就是你下一輪的抽查名單。
4.2 別把不穩定測試跟假綠燈搞混
假綠燈的病是「不會紅」,不穩定測試(flaky test)的病是「常常亂紅」。兩種都要治,但治法不同。
• 不穩定測試的處理:標記隔離、單獨觀察、找出真正的不穩定原因(等待寫法、測試資料互相干擾、環境時序)。
• 不要用「自動重跑三次,有一次綠就算過」來掩蓋。retry 次數調高很方便,但你等於親手製造了一批假綠燈。
五、驗過的事,要留下痕跡
驗證做完就忘記,等於沒做。最省事的做法是在測試檔案裡加一行註解:
// 弄壞驗證:2026-08-21,做法 B(移除產品端年齡檢核),測試如預期變紅。
一年後有人問「這些測試靠得住嗎」,你有答案,而且答案有日期。
5.1 審查 AI 產生的測試時,逐項問這五個問題
• 這支測試宣稱守護什麼行為? 一句話講得出來嗎?講不出來的,先問清楚再談其他。
• 它有斷言嗎? 斷言驗的是那個行為,還是只是畫面上的幾個字?
• 產品邏輯壞掉時,它會紅嗎? 有實際驗過嗎?什麼時候驗的?
• 它會不會根本沒跑到? skip、only、包在 if 裡的斷言。
• 它失敗的時候,訊息看得懂嗎? 半夜 CI 紅了,值班的人能不能靠訊息判斷發生什麼事。
💬 提示詞 4:整批測試的初步盤點
這是剛產生的 20 支測試。請幫我整理成一張表格,每一支列出:
(1) 它宣稱守護的行為,用一句話;
(2) 它的斷言實際驗到哪一層(畫面文字 / 畫面狀態 / API 回應 / 資料狀態);
(3) 如果對應的產品邏輯壞掉,它會不會失敗,以及你判斷的理由。
最後標出你自己最沒把握的三支,說明為什麼。
這一招的價值:讓 AI 先做一次自我盤點,你只要細看它標出來的那三支,再加上自己隨機抽的兩支。二十支的審查工作量,降到五支。它的判斷不保證對,但方向通常是準的。
六、心態:信任要用證據換
這篇的心法一句話:對 AI 產出的測試,信任不是預設值,是用證據累積出來的。
這不是對 AI 的敵意。對人寫的測試,成熟的團隊本來也是這個態度,所以才有程式碼審查。變的只是數量:AI 一天能產出過去一個月的量,驗證的方法必須跟著升級——從逐行讀,升級為 lint 自動擋、結構性抽查,加上定期弄壞一次確認它還會叫。